#! usr/bin/python



from lxml import etree

from core import processing as process
from core import objects as obj

import time
from PyQt4 import QtCore, QtGui
import sys
import re
import threading

class lxml_parser(QtCore.QObject):
	"""
	Main parser object of xml files
	@use the lxml library
	"""
	def __init__(self, spl):#xml_file
		QtCore.QObject.__init__(self)
		self.prefix = "{http://sashimi.sourceforge.net/schema_revision/mzXML_3.1}"
		self.xml_file = spl.getXmlFile()
		#self.pb = QtGui.QProgressBar()
		
		self._spl = spl #obj.Sample(xml_file)

	

# <msRun scanCount="163328" startTime="PT0S" endTime="PT3778.55S" >

	
	def parsing (self, time_window):#pb
		
		max_time, min_time, scan_count = self.getInfos()
		self._spl.setHeader(self.getheader())
		
		"""recuperation de tous les scans 'tagged'"""
		t=time.clock()

		#widget = self.progressBarWidget()
		#widget.show()
		count = 0.; scans =[]
		context = etree.iterparse(self.xml_file, tag= self.prefix + "scan", remove_blank_text=True, remove_comments=True) # remove_pis = True
		for action, elem in context:
			for child in elem.getchildren():
				prec = child.text
				break #precursor premier sous noeud

			scan = obj.Scan({ \
							'scanNumber':int (elem.attrib['num']), \
							'msLevel': int (elem.attrib['msLevel']), \
							'scanType':elem.attrib['scanType'], \
							'retentionTime':process.timeformat(elem.attrib['retentionTime']), \
							'basePeakMz':float (elem.attrib['basePeakMz']), \
							'basePeakIntensity': process.intensityformat(elem.attrib['basePeakIntensity']), \
							'precursorMz':float (prec)})
			scans.append(scan)
			count += 1.
			#self.emit(QtCore.SIGNAL("update_pb"), (count/scan_count)*100)
			#pb.setValue((count/scan_count)*100)
			elem.clear()
			while elem.getprevious() is not None:
				del elem.getparent()[0]
		del context
		
		#Sample construction
		self._spl.setSpectra (process.Spectra_creation(scans, min_time, max_time, time_window))
		self._spl.setChromatogram (process.Chromato_creation(scans))

		del scans
		self.getheader()
		
		print time.clock()-t


#  <scan num="1"
	

	def getInfos (self):
		p = re.compile('\s<msRun\sscanCount="(\d+)"\sstartTime=\"PT(\d+\.\d+|\d+)S"\sendTime=\"PT(\d+\.\d+)S"\s>')
		#max_time = min_time =None

		with open(self.xml_file) as file_handle:
			line = file_handle.readline(); 
			while p.match(line) is None:
				line = file_handle.readline()
			scan_count = int( p.match(line).group(1) )
			max_time = float ( p.match(line).group(3) )
			min_time = float( p.match(line).group(2) )
				
		return  max_time, min_time, scan_count
		
		
	def getheader (self):
		p = re.compile ( '\s+<scan\snum="1"\n') #header until the first scan begins
		header=""
		with open(self.xml_file) as file_handle:
			line = file_handle.readline() 
			while p.match(line) is None:
				header += line
				line = file_handle.readline()
		self._spl.setHeader(str(header))
		
	def getSpl(self):
		return self._spl
	
	
	def build_models(self, chrom_model, spectr_model):
		"""
		create model for the treeView Warning not safe launch in the thread 
		"""
		
		#begin by spectra
		root_spectr =QtGui.QStandardItem(self._spl.getXmlFile())
		for spectr in self._spl.getSpectra():
			child = QtGui.QStandardItem(QtGui.QIcon(QtGui.QPixmap("gui\\icons\\spectrumicon.png")), (str(spectr.t_min)))
			child.setEditable(False)
			root_spectr.appendRow(child)
		spectr_model.appendRow(root_spectr)
		
		root_chrom = QtGui.QStandardItem(QtGui.QIcon(QtGui.QPixmap("gui\\icons\\3d.png")), self._spl.getXmlFile())
		#end with chromas
		for mass in self._spl.getChromatogram():
			child = QtGui.QStandardItem(QtGui.QIcon(QtGui.QPixmap("gui\\icons\\peakicon.png")), str(mass.transition[0])+"/"+str(mass.transition[1]))
			root_chrom.appendRow(child)
			child.setEditable(False)
		chrom_model.appendRow(root_chrom)
	
	def estimate_runtime(self, scans):
		"""
		estimate the time of one scan if user does not get it
		"""
		#<precursorMz precursorIntensity="0" >97</precursorMz>
		#retentionTime="PT0.0101S"

		prec = re.compile('\s+<precursorMz precursorIntensity="\d+" >(\d+)</precursorMz>\n')
		rt = re.compile('retentionTime="(PT\d+\.\d+S)"\n')
		with open(self.xmlfile) as f:
			line = f.readline();i=1
			#getting the first rt and the first prec
			while rt.match(line) is None:
				line =f.readline();i+=1
			rt_0 = process.timeformat(rt.match(line).group(1))
			while prec.match(line) is None:
				line =f.readline();i+=1
			prec_0 = float(prec.match(line).group(1))
			#done
			#getting next while new prec < prec_0
			next_prec = None; new_rt =None
			while next_prec < prec_0 :
				while rt.match(line) is None:
					line =f.readline();i+=1
				new_rt = process.timeformat(rt.match(line).group(1))
				while prec.match(line) is None:
					line =f.readline();i+=1
				next_prec = float(prec.match(line).group(1))
			#emission
			self.emit(QtCore.SIGNAL("runtime_emitted(float)"), abs(new_rt - rt_0))
	


if __name__=="__main__":
	app = QtGui.QApplication(sys.argv)
	parser = lxml_parser( "/home/marco/Bureau/msapipe/output-s6.mzXML",3.03 )
	parser.parsing()
	app.exec_()


